package cn.zsc.netdisk.component;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.sun.glass.ui.View;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

/**
 * @author ccying
 * @date 2021/2/21
 */
@Component
public class MyRedisTemplate {
    private static Map<Integer, RedisTemplate<String, Object>> redisTemplates;
    private final String DEFAULT_HOSTNAME = "localhoost";
    private final int DEFAULT_DATABASE = 0;
    private int DEFAULT_PORT = 6379;
    @Value("${my.redis.host}")
    private String host;
    @Value("${my.redis.port}")
    private int port;
    @Value("${my.redis.username}")
    private String username;
    @Value("${my.redis.password}")
    private String password;
    @Value("${my.redis.dbCapacity}")
    private int dbCapacity;

    private MyRedisTemplate() {
    }

    @PostConstruct
    public void init() {
        int capacity = (int) (this.dbCapacity * 1.0  / 0.75 + 1);
        int initialCapacity = 1;
        while (initialCapacity < capacity) {
            initialCapacity <<= 1;
        }
        if (redisTemplates == null) {
            redisTemplates = new HashMap<>(initialCapacity);
        }
        for (int i = 0; i < dbCapacity; i++) {
            redisTemplates.put(i, redisTemplate(i));
        }
    }

    public RedisTemplate<String, Object> redisTemplate(int database) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory(database));

        StringRedisSerializer keySerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer<Object> valueSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
        valueSerializer.setObjectMapper(mapper);

        redisTemplate.setKeySerializer(keySerializer);
        redisTemplate.setValueSerializer(valueSerializer);
        redisTemplate.setDefaultSerializer(valueSerializer);

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    public LettuceConnectionFactory redisConnectionFactory(int database) {
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        configuration.setHostName(host);
        configuration.setPort(port);
        configuration.setDatabase(database);
        LettuceConnectionFactory factory = new LettuceConnectionFactory(configuration);
        factory.afterPropertiesSet();
        return factory;
    }

    public RedisTemplate<String, Object> get(int i) {
        if (i >= dbCapacity) {
            //返回默认数据库
            return redisTemplates.get(0);
        }
        return redisTemplates.get(i);
    }
}
